package com.example.eamh2system.netty;

import com.digitalpetri.modbus.codec.ModbusRequestEncoder;
import com.digitalpetri.modbus.codec.ModbusResponseDecoder;
import com.example.eamh2system.netty.code.ModbusDecoder;
import com.example.eamh2system.netty.code.ModbusEncoder;
import com.example.eamh2system.netty.handler.H2IdleStateTrigger;
import com.example.eamh2system.netty.handler.H2NettyClientHandler;
import com.example.eamh2system.netty.handler.H2NettyServerHandler;
import com.example.eamh2system.netty.message.ModbusRequest;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
@Data
@Slf4j
public class H2NettyClient implements Runnable{

    /**
     * 当前port
     */
    @Value("${Tcp.port}")
    int port ;
    /**
     * 声明通道
     */
    private Channel channel;
    /**
     * 声明channelFuture
     */
    private ChannelFuture channelFuture;

    NioEventLoopGroup group = new NioEventLoopGroup();
    Bootstrap bootstrap = new Bootstrap();

    @Autowired
    private H2IdleStateTrigger h2IdleStateTrigger;
    @Autowired
    private H2NettyClientHandler h2NettyClientHandler;

    public void start() {
        new Thread(this::run).start();
    }

    @Override
    public void run() {
        log.info("启动客户端");
        group = new NioEventLoopGroup();
        try {
            bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel channel) throws Exception {
                            ChannelPipeline pipeline = channel.pipeline();
                            pipeline.addLast(new IdleStateHandler(0,2,0, TimeUnit.SECONDS));
                            pipeline.addLast(h2IdleStateTrigger);
                            pipeline.addLast("encoder",new ModbusEncoder());
                            pipeline.addLast("decoder",new ModbusDecoder());
                            pipeline.addLast("channelHandler", h2NettyClientHandler);
                        }
                    });
            doConnect();
//            ChannelFuture  ch = bootstrap.connect("127.0.0.1", 8080).sync();
//            ch.addListener((ChannelFutureListener) futureListener -> {
//                if (futureListener.isSuccess()) {
//                    log.info("连接服务器成功");
//
//                } else {
//                    log.warn("连接服务器失败");
//                }
//            });
        } catch(Exception e){
            e.printStackTrace();
        } finally{
            //       group.shutdownGracefully();
        }
    }

    private List<String> ipAddresses= Arrays.asList("127.0.0.1","10.18.10.199");
    private int currentIpIndex = 0;

    public void doConnect() {
        if (channel != null && channel.isActive()) {
            return;
        }
        String host = ipAddresses.get(currentIpIndex);
        ChannelFuture future = bootstrap.connect(host, port);
        future.addListener((ChannelFutureListener) futureListener -> {
            if (futureListener.isSuccess()) {
                log.info("连接服务器成功: " + host + ":" + port);
                channel = futureListener.channel(); // 保存连接的Channel
                // 构造 Modbus 请求消息
                ModbusRequest request = new ModbusRequest(); // 读取从线圈地址0开始的10个线圈状态
                request.setStartAddress(0);
                request.setQuantity(10);
                // 发送请求消息
                channel.writeAndFlush(request);
                // 添加连接关闭监听器
                channel.closeFuture().addListener((ChannelFutureListener) closeFuture -> {
                    log.info("连接断开，开始重连...");
                    // 在连接断开时触发重连操作
                    connectToNextIp();
                });
            } else {
                log.info("连接失败，切换到备用IP并尝试连接其他IP...");
                switchToNextIp();
                // 如果连接失败，使用定时任务进行重连
                futureListener.channel().eventLoop().schedule(() -> doConnect(), 10, TimeUnit.SECONDS);
            }
        });
    }
        private void switchToNextIp() {
            currentIpIndex = (currentIpIndex + 1) % ipAddresses.size();
        }
        private void connectToNextIp() {
            switchToNextIp();
            String nextHost = ipAddresses.get(currentIpIndex);
            log.info("开始连接下一个IP: " + nextHost + ":" + port);
            ChannelFuture future = bootstrap.connect(nextHost, port);
            // 添加连接成功监听器
            future.addListener((ChannelFutureListener) futureListener -> {
                if (futureListener.isSuccess()) {
                    log.info("连接成功: " + nextHost + ":" + port);
                    channel = futureListener.channel(); // 保存连接的Channel
                    // 添加连接关闭监听器
                    channel.closeFuture().addListener((ChannelFutureListener) closeFuture -> {
                        log.info("连接断开，开始重连...");
                        // 在连接断开时触发重连操作
                        connectToNextIp();
                    });
                } else {
                    log.info("连接失败，切换到备用IP并尝试连接其他IP...");
                    switchToNextIp();
                    // 如果连接失败，使用定时任务进行重连
                    futureListener.channel().eventLoop().schedule(() -> connectToNextIp(), 10, TimeUnit.SECONDS);
                }
            });
        }
    }